package com.kx.talk.service.impl;

import com.kx.base.util.PropertiesUtil;
import com.kx.base.vo.UserVO;
import com.kx.talk.cache.UserCache;
import com.kx.talk.client.UserClient;
import com.kx.talk.mapper.*;
import com.kx.talk.pojo.*;
import com.kx.talk.service.FriendService;
import com.kx.talk.settings.FriendPolicySetting;
import com.kx.talk.vo.FriendRequestAddVO;
import com.kx.talk.vo.FriendVO;
import com.kx.talk.vo.PolicyVO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author Sun
 * @Date 2021/7/28 19:29
 */
@Service
public class FriendServiceImpl implements FriendService {
    /**
     * 用户组的最大值
     */
    public static final int GROUP_NUM_MAX = 10;
    @Resource
    private FriendBaseMapper friendBaseMapper;

    @Resource
    private FriendGroupMapper friendGroupMapper;

    @Resource
    private UserFriendShipPolicyMapper userFriendShipPolicyMapper;

    @Resource
    private FriendRelationMapper friendRelationMapper;

    @Resource
    private FriendRequestAddMapper friendRequestAddMapper;

    @Resource
    private FriendRequestAddDao friendRequestAddDao;

    @Resource
    private UserClient userClient;

    @Resource
    private TempUserMapper tempUserMapper;

    @Resource
    private TempUserDao tempUserDao;

    @Resource
    private FriendGroupDao friendGroupDao;

    @Resource
    private FriendDao friendDao;

    @Resource
    private UserCache userCache;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int insertFriendBase(Long userId) {
        FriendBase friendBase = new FriendBase();
        friendBase.setUserId(userId);
        friendBase.setFriendShipPolicyId(1);
        //有一个好友实体
        int result = friendBaseMapper.insertSelective(friendBase);
        //好友实体应该有两个默认的分组
        //我的好友
        FriendGroup friendGroup = new FriendGroup();
        friendGroup.setUserId(userId);
        friendGroup.setName("我的好友");
        friendGroup.setOrderIndex(1);
        result += friendGroupMapper.insertSelective(friendGroup);
        //黑名单
        friendGroup.setUserId(userId);
        friendGroup.setName("黑名单");
        friendGroup.setOrderIndex(99);
        result += friendGroupMapper.insertSelective(friendGroup);
        return result;
    }

    @Override
    public List<PolicyVO> selectPolicies() {
        List<UserFriendShipPolicy> policies = userFriendShipPolicyMapper.selectByExample(null);
        List<PolicyVO> policyVOS = new ArrayList<>();
        if (policies != null && policies.size() > 0) {
            for (UserFriendShipPolicy policy : policies) {
                PolicyVO policyVO = new PolicyVO();
                //复制vo对象
                PropertiesUtil.copy(policy, policyVO);
                policyVOS.add(policyVO);
            }
        }
        return policyVOS;
    }

    @Override
    public int updatePolicyByUid(Long userId, Integer policyId, String question, String answer, String password) {
        FriendBaseExample example = new FriendBaseExample();
        FriendBaseExample.Criteria criteria = example.createCriteria();
        criteria.andUserIdEqualTo(userId);
        //写入数据的对象
        FriendBase friendBase = new FriendBase();
        //写入的数据结合policyId的取值，多种情况
        if (policyId.equals(FriendPolicySetting.POLICY_ID_1)) {
            friendBase.setFriendShipPolicyId(1);
        } else if (policyId.equals(FriendPolicySetting.POLICY_ID_2)) {
            //写入问题和答案
            friendBase.setFriendShipPolicyId(2);
            friendBase.setFriendPolicyQuestion(question);
            friendBase.setFriendPolicyAnswer(answer);
        } else if (policyId.equals(FriendPolicySetting.POLICY_ID_3)) {
            //写入密码
            friendBase.setFriendShipPolicyId(3);
            friendBase.setFriendPolicyPassword(password);
        } else if (policyId.equals(FriendPolicySetting.POLICY_ID_4)) {
            //验证信息
            friendBase.setFriendShipPolicyId(4);
        } else if (policyId.equals(FriendPolicySetting.POLICY_ID_4)) {
            friendBase.setFriendShipPolicyId(5);
        }
        return friendBaseMapper.updateByExampleSelective(friendBase, example);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int addFriend(Long userId, Long wantId, String message, Integer groupId) {
        //用户组必须存在,如果用户组不存在，就直接添加失败
        FriendGroup friendGroup = friendGroupMapper.selectByPrimaryKey(groupId);
        if (friendGroup == null) {
            //组不存在
            return 0;
        }
        //不同用户wantId的好友策略不同，处理逻辑也不一样
        //所以先查询wantId对应的用户的好友策略
        FriendBaseExample example = new FriendBaseExample();
        FriendBaseExample.Criteria criteria = example.createCriteria();
        criteria.andUserIdEqualTo(wantId);
        List<FriendBase> friendBases = friendBaseMapper.selectByExample(example);
        if (friendBases == null || friendBases.size() == 0) {
            //目标用户不存在
            return 0;
        }

        //拿到该用户的处理策略的基本信息
        FriendBase friendBase = friendBases.get(0);
        //拿到该用户添加好友的处理策略
        Integer policyId = friendBase.getFriendShipPolicyId();

        //验证是否成功的标志位
        int result = 0;

        if (policyId.equals(FriendPolicySetting.POLICY_ID_1)) {
            //直接添加通过，无需验证
            result = 1;
        } else if (policyId.equals(FriendPolicySetting.POLICY_ID_2)) {
            //验证问题，判断是否验证成功
            if (friendBase.getFriendPolicyAnswer().equals(message)) {
                //答案正确，验证通过
                result = 1;
            } else {
                result = 0;
            }
        } else if (policyId.equals(FriendPolicySetting.POLICY_ID_3)) {
            //验证密码，判断是否验证成功
            if (friendBase.getFriendPolicyPassword().equals(message)) {
                //密码正确，验证通过
                result = 1;
            } else {
                result = 0;
            }
        } else if (policyId.equals(FriendPolicySetting.POLICY_ID_4)) {
            //发送验证消息，等待对方验证通过
            //保存验证信息到数据库中
            FriendRequestAdd friendRequestAdd = new FriendRequestAdd();
            friendRequestAdd.setUserId(userId);
            friendRequestAdd.setRequestUserId(wantId);
            friendRequestAdd.setMessage(message);
            friendRequestAdd.setState(0);
            friendRequestAddMapper.insertSelective(friendRequestAdd);
            result = 2;

        } else if (policyId.equals(FriendPolicySetting.POLICY_ID_5)) {
            //拒绝添加
            return 0;
        } else {
            //POLICY_ID有问题
            return 0;
        }


        //只要result==1 就说明 验证通过了
        if (result == 1) {
            //因为添加成功后，好友的关系是双向的，你既是他的好友他也是你的好友
            //所以需要在friend_relation表中插入两条记录

            //首先应该判断两个是否已经建立了好友关系了，建立了就不用重复添加了
            //这这里我们的业务逻辑是好友之间可以单向建立好友关系
            //比如你朋友把你删了，在你的好友列表中还存在，但是你和他发送消息，需要验证，加回好友，才能继续聊天
            FriendRelationExample friendRelationExample = new FriendRelationExample();
            FriendRelationExample.Criteria exampleCriteria = friendRelationExample.createCriteria();
            exampleCriteria.andUserIdEqualTo(userId);
            exampleCriteria.andFriendIdEqualTo(wantId);
            List<FriendRelation> friendRelations = friendRelationMapper.selectByExample(friendRelationExample);

            if (friendRelations == null || friendRelations.size() == 0) {
                //说明userId和wantId没有建立好友关系
                FriendRelation friendRelation = new FriendRelation();
                friendRelation.setUserId(userId);
                friendRelation.setFriendId(wantId);
                friendRelation.setFriendGroupId(groupId);
                friendRelationMapper.insertSelective(friendRelation);
            }

            friendRelationExample = new FriendRelationExample();
            exampleCriteria = friendRelationExample.createCriteria();
            exampleCriteria.andUserIdEqualTo(userId);
            exampleCriteria.andFriendIdEqualTo(wantId);
            friendRelations = friendRelationMapper.selectByExample(friendRelationExample);

            if (friendRelations == null || friendRelations.size() == 0) {
                //说明wantId和userId没有建立好友关系
                FriendRelation friendRelation = new FriendRelation();
                friendRelation.setUserId(wantId);
                friendRelation.setFriendId(userId);
                friendRelation.setFriendGroupId(groupId);
                friendRelationMapper.insertSelective(friendRelation);
            }

        }
        return result;
    }

    @Override
    public Long askRequest(Long id, Long userId, Integer state, Long groupId) {
        //1、根据id查（userId与requestId）
        FriendRequestAdd friendRequestAdd = friendRequestAddMapper.selectByPrimaryKey(id);
        if (friendRequestAdd == null || !(userId.equals(friendRequestAdd.getRequestUserId()))) {
            //数据有问题，当前登录的用户无权同意/拒绝这个请求
            return null;
        }
        //2、把所有的userId请求requestId的数据全都查询出来的条件。
        FriendRequestAddExample example = new FriendRequestAddExample();
        FriendRequestAddExample.Criteria criteria = example.createCriteria();
        criteria.andUserIdEqualTo(friendRequestAdd.getUserId());
        criteria.andRequestUserIdEqualTo(friendRequestAdd.getRequestUserId());
        //3、根据上述条件过滤出来的这些记录的state都置为参数@param state。
        FriendRequestAdd requestAdd = new FriendRequestAdd();
        requestAdd.setState(state);
        //更新数据库中的state
        friendRequestAddMapper.updateByExampleSelective(requestAdd, example);
        //4、如果state==1，就是同意，那就得给双方添加双向的好友关系。
        if (state == 1) {
            FriendRelationExample friendRelationExample = new FriendRelationExample();
            FriendRelationExample.Criteria exampleCriteria = friendRelationExample.createCriteria();
            exampleCriteria.andUserIdEqualTo(userId);
            exampleCriteria.andFriendIdEqualTo(friendRequestAdd.getRequestUserId());
            List<FriendRelation> friendRelations = friendRelationMapper.selectByExample(friendRelationExample);

            if (friendRelations == null || friendRelations.size() == 0) {
                //说明userId和wantId没有建立好友关系
                FriendRelation friendRelation = new FriendRelation();
                friendRelation.setUserId(friendRequestAdd.getUserId());
                friendRelation.setFriendId(friendRequestAdd.getRequestUserId());
                friendRelation.setFriendGroupId(1);
                friendRelationMapper.insertSelective(friendRelation);
            }

            friendRelationExample = new FriendRelationExample();
            exampleCriteria = friendRelationExample.createCriteria();
            exampleCriteria.andUserIdEqualTo(friendRequestAdd.getUserId());
            exampleCriteria.andFriendIdEqualTo(friendRequestAdd.getRequestUserId());
            friendRelations = friendRelationMapper.selectByExample(friendRelationExample);

            if (friendRelations == null || friendRelations.size() == 0) {
                //说明wantId和userId没有建立好友关系
                FriendRelation friendRelation = new FriendRelation();
                friendRelation.setUserId(friendRequestAdd.getRequestUserId());
                friendRelation.setFriendId(friendRequestAdd.getUserId());
                friendRelation.setFriendGroupId(1);
                friendRelationMapper.insertSelective(friendRelation);
            }
        }
        return friendRequestAdd.getUserId();
    }

    @Override
    public List<FriendRequestAddVO> selectRequestByPage(Long userId, Integer lastItemId, Integer pageSize) {
        List<FriendRequestAddVO> list = null;
        if (lastItemId == null) {
            //查第一页
            list = friendRequestAddDao.selectRequestFirstPage(userId, pageSize);
        } else {
            //查其它页
            list = friendRequestAddDao.selectRequestPage(userId, lastItemId, pageSize);
        }
        //1.获取添加当前用户的所有用户id,所有id组成一个集合
        List<Long> userIds = new ArrayList<>();
        for (FriendRequestAddVO friendRequestAddVO : list) {
            userIds.add(friendRequestAddVO.getUserId());
        }
        List<UserVO> userVOS = userCache.getUsers(userIds);
        //***** 编程技巧，避免使用final使得内存中常量变多。
        //关联数据
        for (int i = 0; i < list.size(); i++) {
            FriendRequestAddVO friendRequestAddVO = list.get(i);
            for (int j = 0; j < userVOS.size(); j++) {
                if (friendRequestAddVO.getUserId().equals(userVOS.get(j).getId())) {
                    friendRequestAddVO.setUser(userVOS.get(j));
                }
            }
        }
        return list;
    }

    @Override
    public List<FriendGroup> selectGroupsByUserId(Long userId) {
        FriendGroupExample example = new FriendGroupExample();
        FriendGroupExample.Criteria criteria = example.createCriteria();
        criteria.andUserIdEqualTo(userId);
        example.setOrderByClause("order_index");

        List<FriendGroup> friendGroups = friendGroupMapper.selectByExample(example);
        return friendGroups;
    }

    @Override
    public int createGroup(Long userId, String groupName) {
        FriendGroupExample example = new FriendGroupExample();
        FriendGroupExample.Criteria criteria = example.createCriteria();
        criteria.andUserIdEqualTo(userId);
        //1.查询当前用户组数量，并判断是否到达上线
        long count = friendGroupMapper.countByExample(example);
        if (count > GROUP_NUM_MAX) {
            //用户组数量到达上线
            return 2;
        }
        //2.判断用户组名是否已经存在
        FriendGroupExample exampleGroupName = new FriendGroupExample();
        FriendGroupExample.Criteria criteriaGroupName = exampleGroupName.createCriteria();
        criteriaGroupName.andUserIdEqualTo(userId);
        criteriaGroupName.andNameEqualTo(groupName);
        List<FriendGroup> friendGroups_names = friendGroupMapper.selectByExample(exampleGroupName);
        if (friendGroups_names != null && friendGroups_names.size() > 0) {
            return 3;
        }

        //3.需要查询出当前组的第二大orderIndex,因为最大的orderIndex是黑名单
        criteria.andOrderIndexNotEqualTo(99);
        example.setOrderByClause("order_index desc");
        List<FriendGroup> friendGroups = friendGroupMapper.selectByExample(example);
        if (friendGroups != null && friendGroups.size() > 0) {
            int orderIndex = friendGroups.get(0).getOrderIndex();
            orderIndex++;
            FriendGroup friendGroup = new FriendGroup();
            friendGroup.setOrderIndex(orderIndex);
            friendGroup.setName(groupName);
            friendGroup.setUserId(userId);
            return friendGroupMapper.insertSelective(friendGroup);
        }
        return 0;
    }

    @Override
    public int editFriendToGroup(Long userId, Long friendId, Integer groupId) {
        //校验好友是不是存在
        FriendRelationExample example = new FriendRelationExample();
        FriendRelationExample.Criteria criteria = example.createCriteria();
        criteria.andUserIdEqualTo(userId);
        criteria.andFriendIdEqualTo(friendId);
        List<FriendRelation> friendRelations = friendRelationMapper.selectByExample(example);
        if (friendRelations == null && friendRelations.size() == 0) {
            return 2;
        }
        //校验组是不是存在
        FriendGroupExample friendGroupExample = new FriendGroupExample();
        FriendGroupExample.Criteria friendGroupExampleCriteria = friendGroupExample.createCriteria();
        friendGroupExampleCriteria.andUserIdEqualTo(userId);
        friendGroupExampleCriteria.andIdEqualTo(groupId);
        List<FriendGroup> friendGroups = friendGroupMapper.selectByExample(friendGroupExample);
        if (friendGroups == null || friendGroups.size() == 0) {
            return 3;
        }

        //修改分组
        FriendRelation friendRelation = new FriendRelation();
        friendRelation.setFriendGroupId(groupId);
        return friendRelationMapper.updateByExampleSelective(friendRelation, example);
    }

    @Override
    public int editFriendMarkName(Long userId, Long friendId, String markName) {
        //校验好友是不是存在
        FriendRelationExample example = new FriendRelationExample();
        FriendRelationExample.Criteria criteria = example.createCriteria();
        criteria.andUserIdEqualTo(userId);
        criteria.andFriendIdEqualTo(friendId);
        List<FriendRelation> friendRelations = friendRelationMapper.selectByExample(example);
        if (friendRelations == null || friendRelations.size() == 0) {
            return 2;
        }

        //修改分组
        FriendRelation friendRelation = new FriendRelation();
        friendRelation.setMarkName(markName);
        return friendRelationMapper.updateByExampleSelective(friendRelation, example);
    }

    @Override
    public int updateGroupName(Long userId, Integer groupId, String groupName) {
        //  //查userId有没有groupId这个组
        FriendGroup friendGroup = friendGroupMapper.selectByPrimaryKey(groupId);
        if (friendGroup == null) {
            return 2;
        } else if (!friendGroup.getUserId().equals(userId)) {
            return 2;
        }
        //设置可以操作的组的名称
        friendGroup.setName(groupName);
        //返回执行结果
        return friendGroupMapper.updateByPrimaryKey(friendGroup);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int delGroup(Long userId, Integer groupId) {
        FriendGroup friendGroup = friendGroupMapper.selectByPrimaryKey(groupId);
        if (friendGroup == null) {
            return 2;
        } else if (!friendGroup.getUserId().equals(userId)) {
            return 2;
        }
        //判断分组内有没有好友，如果有好友将好友移入默认分组我的好友中
        FriendRelationExample friendRelationExample = new FriendRelationExample();
        FriendRelationExample.Criteria criteria = friendRelationExample.createCriteria();
        criteria.andFriendGroupIdEqualTo(groupId);
        List<FriendRelation> friendRelations = friendRelationMapper.selectByExample(friendRelationExample);
        if (friendRelations != null || friendRelations.size() > 0) {
            //将组内所有好友移入我的好友中
            for (int i = 0; i < friendRelations.size(); i++) {
                FriendRelation friendRelation = new FriendRelation();
                friendRelation.setFriendGroupId(1);
                friendRelationMapper.updateByExampleSelective(friendRelation, friendRelationExample);
            }
        }
        //删除好友分组，将本好友分组后面的排序索引-1,注意写sql，避免索引失效
        Integer orderIndex = friendGroup.getOrderIndex();
        friendGroupDao.editBatchOrderIndexByUserId(userId, orderIndex);
        return friendGroupMapper.deleteByPrimaryKey(groupId);
    }

    @Override
    public List<FriendVO> findFriends(Long userId) {
        //查询出来的数据中user信息是空的，所以需要将用户信息填充进去
        //使用分级缓存的策略
        List<FriendVO> friendVOS = friendDao.findFriendsByUserId(userId);
        if (friendVOS == null || friendVOS.size() == 0) {
            //没有好友
            return null;
        }
        //friendVOs里有一组userId，想要获取userVO对象
        List<Long> userIds = new ArrayList<>();
        for (FriendVO friendVO : friendVOS) {
            Long friendId = friendVO.getFriendId();
            if (friendId == null) {
                continue;
            }
            userIds.add(friendId);
        }
        //根据用户id的集合将所有的用户信息查询出来，1.缓存 2.当前服务备份数据库 3.其他服务数据库
        List<UserVO> userVOS = userCache.getUsers(userIds);
        for (UserVO userVO : userVOS) {
            for (FriendVO friendVO : friendVOS) {
                if (userVO==null){
                    break;
                }
                if (userVO.getId().equals(friendVO.getFriendId())) {
                    friendVO.setUser(userVO);
                }
            }
        }
        return friendVOS;
    }
}
